With the Vue Test Utils library, we can write and run unit tests for Vue apps easily.
In this article, we’ll look at how to write unit tests with the Vue Test Utils library.
Emitting Event from Child Component
We can check for events that are emitted in a child component.
To do that, we call mount
to mount the parent component with the child component.
Then we can emit the event we want on the child:
import { mount } from '@vue/test-utils'
const ChildComponent = {
template: `
<div>
<p>child</p>
</div>
`,
}
const ParentComponent = {
template: `
<div>
<child-component @custom="onCustom" />
<p id='emitted' v-if="emitted">emitted</p>
</div>
`,
data() {
return { emitted: false }
},
methods: {
onCustom() {
this.emitted = true
}
},
components: {
ChildComponent
}
}
describe('ParentComponent', () => {
it('shows emitted when child-component emits custom event', async () => {
const wrapper = mount(ParentComponent)
await wrapper.findComponent(ChildComponent).vm.$emit('custom')
expect(wrapper.find('#emitted').text()).toContain('emitted')
})
})
To mount the child component of ParentComponent
with the ParentComponent
, we call the mount
method.
The findComponent
method has ChildComponent
as the argument so that we can use the returned component wrapper to emit the custom
event with the $emit
method.
Then to check if the ‘emitted’ text is displayed, we call the find
method to check if it has the 'emitted'
string.
Manipulating Component State
We can manipulate component state with the setData
or setProps
method.
For example, we can write:
import { mount } from '@vue/test-utils'
const Counter = {
template: `
<div>
<p>{{count}}</p>
</div>
`,
data() {
return { count: 0 }
},
}
describe('Counter', () => {
it('renders 10 for count', async () => {
const wrapper = mount(Counter)
await wrapper.setData({ count: 10 })
expect(wrapper.find('p').text()).toContain(10)
})
})
to call the setData
method with the data we want to set.
The key is the key of a reactive property and the value is its value.
To set props, we can use the setProps
method:
import { mount } from '@vue/test-utils'
const Foo = {
template: `
<div>
<p>{{foo}}</p>
</div>
`,
props: ['foo']
}
describe('Foo', () => {
it('renders bar for foo prop', async () => {
const wrapper = mount(Foo)
await wrapper.setProps({ foo: 'bar' })
expect(wrapper.find('p').text()).toContain('bar')
})
})
We call the setProps
method to set the value of the foo
prop to 'bar'
.
Then we check that if that is rendered in the last line of the test.
Props can also be set when we mount the component:
import { mount } from '@vue/test-utils'
const Foo = {
template: `
<div>
<p>{{foo}}</p>
</div>
`,
props: ['foo']
}
describe('Foo', () => {
it('renders bar for foo prop', async () => {
const wrapper = mount(Foo, {
propsData: {
foo: 'bar'
}
})
expect(wrapper.find('p').text()).toContain('bar')
})
})
The 2nd argument of the mount
method takes the propsData
property to let us mock the props.
Conclusion
We can mock props and set values of reactive properties in our tests and test them.
Child component events can also be tested from the parent.